#include "dtu_ini.h"
#include "dtu_log.h"
#include "dtu_memory.h"
#include <sys/stat.h>
#include <ctype.h>
#include <strings.h>

/* 内部函数声明 */
static char* trim_whitespace(char* str);
static dtu_error_t find_section_line(FILE* fp, const char* section, long* section_pos);
static dtu_error_t find_key_line(FILE* fp, const char* key, long section_pos, long* key_pos, char* value, size_t value_size);
static dtu_error_t update_key_value(const char* filename, const char* section, const char* key, const char* value);

/* 去除字符串首尾空白字符 */
static char* trim_whitespace(char* str)
{
    char* end;
    
    /* 去除开头空白 */
    while (isspace((unsigned char)*str)) str++;
    
    if (*str == 0) return str;
    
    /* 去除结尾空白 */
    end = str + strlen(str) - 1;
    while (end > str && isspace((unsigned char)*end)) end--;
    
    end[1] = '\0';
    return str;
}

/* 查找节位置 */
static dtu_error_t find_section_line(FILE* fp, const char* section, long* section_pos)
{
    char line[512];
    char section_header[128];
    
    snprintf(section_header, sizeof(section_header), "[%s]", section);
    
    rewind(fp);
    while (fgets(line, sizeof(line), fp)) {
        char* trimmed = trim_whitespace(line);
        if (strcmp(trimmed, section_header) == 0) {
            *section_pos = ftell(fp);
            return DTU_OK;
        }
    }
    
    return DTU_ERROR_NOT_FOUND;
}

/* 查找键值对 */
static dtu_error_t find_key_line(FILE* fp, const char* key, long section_pos, long* key_pos, char* value, size_t value_size)
{
    char line[512];
    
    fseek(fp, section_pos, SEEK_SET);
    
    while (fgets(line, sizeof(line), fp)) {
        char* trimmed = trim_whitespace(line);
        
        /* 遇到下一个节或文件结束 */
        if (trimmed[0] == '[' || trimmed[0] == '\0') {
            break;
        }
        
        /* 跳过注释行 */
        if (trimmed[0] == '#' || trimmed[0] == ';') {
            continue;
        }
        
        /* 查找键值对 */
        char* eq_pos = strchr(trimmed, '=');
        if (eq_pos) {
            /* 不修改原始字符串，而是复制键名部分 */
            size_t key_len = eq_pos - trimmed;
            char key_buffer[256];
            strncpy(key_buffer, trimmed, key_len);
            key_buffer[key_len] = '\0';
            char* key_part = trim_whitespace(key_buffer);

            char* value_part = eq_pos + 1;

            /* 手动处理值部分：只去除开头空白和结尾的换行符，保留所有其他字符 */
            while (isspace((unsigned char)*value_part) && *value_part != '\n' && *value_part != '\r') {
                value_part++;
            }

            /* 去除结尾的换行符和回车符，但保留其他所有字符包括| */
            size_t len = strlen(value_part);
            while (len > 0 && (value_part[len-1] == '\n' || value_part[len-1] == '\r')) {
                value_part[len-1] = '\0';
                len--;
            }
            
            if (strcmp(key_part, key) == 0) {
                if (key_pos) {
                    *key_pos = ftell(fp) - strlen(line);
                }
                if (value && value_size > 0) {
                    DTU_STRNCPY(value, value_part, value_size);
                }
                return DTU_OK;
            }
        }
    }
    
    return DTU_ERROR_NOT_FOUND;
}

/* 更新键值对 */
static dtu_error_t update_key_value(const char* filename, const char* section, const char* key, const char* value)
{
    FILE* fp = fopen(filename, "r");
    if (!fp) {
        return DTU_ERROR_NOT_FOUND;
    }
    
    /* 读取整个文件到内存 */
    fseek(fp, 0, SEEK_END);
    long file_size = ftell(fp);
    rewind(fp);
    
    char* content = DTU_MALLOC(file_size + 1024); /* 额外空间用于新增内容 */
    if (!content) {
        fclose(fp);
        return DTU_ERROR_MEMORY;
    }
    
    size_t read_size = fread(content, 1, file_size, fp);
    fclose(fp);
    content[read_size] = '\0';
    
    /* 查找并更新配置 */
    char* new_content = DTU_MALLOC(file_size + 1024);
    if (!new_content) {
        DTU_FREE(content);
        return DTU_ERROR_MEMORY;
    }
    
    char section_header[128];
    snprintf(section_header, sizeof(section_header), "[%s]", section);
    
    char* section_start = strstr(content, section_header);
    bool section_found = (section_start != NULL);
    bool key_updated = false;
    
    if (section_found) {
        /* 在现有节中查找键 */
        char* line_start = section_start;
        char* next_section = NULL;
        
        /* 查找下一个节的开始 */
        char* search_pos = section_start + strlen(section_header);
        while ((search_pos = strchr(search_pos, '[')) != NULL) {
            if (search_pos == content || *(search_pos - 1) == '\n') {
                next_section = search_pos;
                break;
            }
            search_pos++;
        }
        
        /* 在节内查找键 */
        char key_pattern[256];
        snprintf(key_pattern, sizeof(key_pattern), "\n%s=", key);
        char* key_line = strstr(section_start, key_pattern);
        
        if (key_line && (next_section == NULL || key_line < next_section)) {
            /* 更新现有键 */
            char* value_start = strchr(key_line, '=') + 1;
            char* line_end = strchr(value_start, '\n');
            
            /* 构建新内容 */
            size_t prefix_len = key_line + 1 - content;
            strncpy(new_content, content, prefix_len);
            new_content[prefix_len] = '\0';
            
            strcat(new_content, key);
            strcat(new_content, "=");
            strcat(new_content, value);
            
            if (line_end) {
                strcat(new_content, line_end);
            }
            
            key_updated = true;
        } else {
            /* 在节末尾添加新键 */
            if (next_section) {
                size_t prefix_len = next_section - content;
                strncpy(new_content, content, prefix_len);
                new_content[prefix_len] = '\0';
                
                char new_line[256];
                snprintf(new_line, sizeof(new_line), "%s=%s\n", key, value);
                strcat(new_content, new_line);
                strcat(new_content, next_section);
            } else {
                strcpy(new_content, content);
                char new_line[256];
                snprintf(new_line, sizeof(new_line), "\n%s=%s", key, value);
                strcat(new_content, new_line);
            }
            key_updated = true;
        }
    } else {
        /* 添加新节和键 */
        strcpy(new_content, content);
        char new_section[512];
        snprintf(new_section, sizeof(new_section), "\n[%s]\n%s=%s", section, key, value);
        strcat(new_content, new_section);
        key_updated = true;
    }
    
    /* 写回文件 */
    if (key_updated) {
        fp = fopen(filename, "w");
        if (fp) {
            fwrite(new_content, 1, strlen(new_content), fp);
            fclose(fp);
        }
    }
    
    DTU_FREE(content);
    DTU_FREE(new_content);
    
    return key_updated ? DTU_OK : DTU_ERROR;
}

/* 公共函数实现 */
dtu_error_t dtu_ini_get_string(const char* filename, const char* section, const char* key, 
                               const char* default_value, char* buffer, size_t buffer_size)
{
    if (!filename || !section || !key || !buffer || buffer_size == 0) {
        return DTU_ERROR_INVALID_PARAM;
    }
    
    FILE* fp = fopen(filename, "r");
    if (!fp) {
        if (default_value) {
            DTU_STRNCPY(buffer, default_value, buffer_size);
        } else {
            buffer[0] = '\0';
        }
        return DTU_ERROR_NOT_FOUND;
    }
    
    long section_pos;
    if (find_section_line(fp, section, &section_pos) != DTU_OK) {
        fclose(fp);
        if (default_value) {
            DTU_STRNCPY(buffer, default_value, buffer_size);
        } else {
            buffer[0] = '\0';
        }
        return DTU_ERROR_NOT_FOUND;
    }
    
    if (find_key_line(fp, key, section_pos, NULL, buffer, buffer_size) != DTU_OK) {
        fclose(fp);
        if (default_value) {
            DTU_STRNCPY(buffer, default_value, buffer_size);
        } else {
            buffer[0] = '\0';
        }
        return DTU_ERROR_NOT_FOUND;
    }
    
    fclose(fp);
    return DTU_OK;
}

int dtu_ini_get_int(const char* filename, const char* section, const char* key, int default_value)
{
    char buffer[32];
    if (dtu_ini_get_string(filename, section, key, NULL, buffer, sizeof(buffer)) == DTU_OK) {
        return atoi(buffer);
    }
    return default_value;
}

bool dtu_ini_get_bool(const char* filename, const char* section, const char* key, bool default_value)
{
    char buffer[16];
    if (dtu_ini_get_string(filename, section, key, NULL, buffer, sizeof(buffer)) == DTU_OK) {
        return (strcasecmp(buffer, "true") == 0 || strcmp(buffer, "1") == 0);
    }
    return default_value;
}

dtu_error_t dtu_ini_set_string(const char* filename, const char* section, const char* key, const char* value)
{
    if (!filename || !section || !key || !value) {
        return DTU_ERROR_INVALID_PARAM;
    }
    
    return update_key_value(filename, section, key, value);
}

dtu_error_t dtu_ini_set_int(const char* filename, const char* section, const char* key, int value)
{
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%d", value);
    return dtu_ini_set_string(filename, section, key, buffer);
}

dtu_error_t dtu_ini_set_bool(const char* filename, const char* section, const char* key, bool value)
{
    return dtu_ini_set_string(filename, section, key, value ? "true" : "false");
}

bool dtu_ini_file_exists(const char* filename)
{
    struct stat st;
    return (stat(filename, &st) == 0);
}

dtu_error_t dtu_ini_create_default(const char* filename)
{
    /* 如果文件已存在，不覆盖 */
    if (dtu_ini_file_exists(filename)) {
        return DTU_OK;
    }

    /* 创建config目录（如果不存在） */
    char dir_path[512];
    DTU_STRNCPY(dir_path, filename, sizeof(dir_path));
    char* last_slash = strrchr(dir_path, '/');
    if (last_slash) {
        *last_slash = '\0';
        /* 创建目录，如果不存在 */
        if (access(dir_path, F_OK) != 0) {
            if (mkdir(dir_path, 0755) == 0) {
                printf("Created config directory: %s\n", dir_path);
            } else {
                printf("Warning: Failed to create config directory: %s\n", dir_path);
            }
        }
    }

    /* 创建默认配置文件内容 */
    FILE* fp = fopen(filename, "w");
    if (!fp) {
        return DTU_ERROR_PERMISSION;
    }

    /* 写入默认配置 */
    fprintf(fp, "# DTU配置文件\n");
    fprintf(fp, "# 此文件用于持久化保存DTU系统的所有配置信息\n");
    fprintf(fp, "# 支持断点重启后配置恢复\n\n");

    fprintf(fp, "[device_info]\n");
    fprintf(fp, "device_id=DTU001\n");
    fprintf(fp, "serial_number=SN20240101001\n");
    fprintf(fp, "model=1\n");
    fprintf(fp, "firmware_version=1.0.0\n");
    fprintf(fp, "hardware_version=HW1.0\n\n");

    fprintf(fp, "[rs485_config]\n");
    fprintf(fp, "device=/dev/ttyUSB0\n");
    fprintf(fp, "baudrate=9600\n");
    fprintf(fp, "databits=8\n");
    fprintf(fp, "stopbits=1\n");
    fprintf(fp, "parity=N\n");
    fprintf(fp, "timeout=1000\n\n");

    fprintf(fp, "[rs232_config]\n");
    fprintf(fp, "device=/dev/ttyUSB1\n");
    fprintf(fp, "baudrate=9600\n");
    fprintf(fp, "databits=8\n");
    fprintf(fp, "stopbits=1\n");
    fprintf(fp, "parity=N\n");
    fprintf(fp, "timeout=1000\n\n");

    fprintf(fp, "[ethernet_config]\n");
    fprintf(fp, "dhcp_enable=true\n");
    fprintf(fp, "ip=192.168.1.100\n");
    fprintf(fp, "netmask=255.255.255.0\n");
    fprintf(fp, "gateway=192.168.1.1\n");
    fprintf(fp, "dns1=8.8.8.8\n");
    fprintf(fp, "dns2=8.8.4.4\n\n");

    fprintf(fp, "[wifi_config]\n");
    fprintf(fp, "ssid=\n");
    fprintf(fp, "password=\n");
    fprintf(fp, "security_type=2\n\n");

    fprintf(fp, "[lte_config]\n");
    fprintf(fp, "apn=cmnet\n");
    fprintf(fp, "username=\n");
    fprintf(fp, "password=\n");
    fprintf(fp, "pin_code=0\n\n");

    fprintf(fp, "[collect_config]\n");
    fprintf(fp, "interval=30\n");
    fprintf(fp, "auto_collect=true\n");
    fprintf(fp, "retry_count=3\n");
    fprintf(fp, "retry_interval=5\n\n");

    fprintf(fp, "[push_config]\n");
    fprintf(fp, "protocol=0\n");
    fprintf(fp, "format=0\n");
    fprintf(fp, "server_host=mqtt.example.com\n");
    fprintf(fp, "server_port=1883\n");
    fprintf(fp, "username=\n");
    fprintf(fp, "password=\n");
    fprintf(fp, "topic=dtu/data\n");
    fprintf(fp, "client_id=DTU001\n");
    fprintf(fp, "timeout=30\n");
    fprintf(fp, "retry_count=3\n");
    fprintf(fp, "retry_interval=5\n");
    fprintf(fp, "enable_ssl=false\n");
    fprintf(fp, "enable_compression=false\n");
    fprintf(fp, "keepalive=60\n");
    fprintf(fp, "clean_session=true\n\n");

    fprintf(fp, "[mqtt_subscribe]\n");
    fprintf(fp, "topic=dtu/DTU001/command\n");
    fprintf(fp, "qos=1\n\n");

    fprintf(fp, "[modbus_device_count]\n");
    fprintf(fp, "count=1\n\n");

    fprintf(fp, "[modbus_device_1]\n");
    fprintf(fp, "id=1\n");
    fprintf(fp, "name=设备1\n");
    fprintf(fp, "enabled=1\n");
    fprintf(fp, "crc_enable=1\n");
    fprintf(fp, "poll_string=010300000001\n");
    fprintf(fp, "serial_port=rs485\n");
    fprintf(fp, "description=读取保持寄存器地址0，数量1\n\n");

    fprintf(fp, "[web_config]\n");
    fprintf(fp, "port=10020\n");
    fprintf(fp, "username=admin\n");
    fprintf(fp, "password=admin123\n");
    fprintf(fp, "enable_auth=true\n");
    fprintf(fp, "session_timeout=3600\n\n");

    fprintf(fp, "[system_config]\n");
    fprintf(fp, "log_level=1\n");
    fprintf(fp, "enable_watchdog=true\n");
    fprintf(fp, "watchdog_timeout=30\n");
    fprintf(fp, "enable_auto_restart=true\n");

    fclose(fp);

    return DTU_OK;
}
